#include <iostream>
#include <string>
#include <websocketpp/server.hpp>
#include <websocketpp/config/asio_no_tls.hpp> // 非ssl/tls加密
#include <functional>

typedef websocketpp::server<websocketpp::config::asio> wsserver_t;

void print(const std::string& str)
{
    std::cout << str << std::endl;
}
void http_callback(wsserver_t *svr, websocketpp::connection_hdl hdl)
{
    std::cout << "收到http请求" << std::endl;

    /* 给客户端返回一个hello world页面 */

    wsserver_t::connection_ptr conn = svr->get_con_from_hdl(hdl);
    std::cout << "request body: " << conn->get_request_body() << std::endl; // 获取请求正文
    websocketpp::http::parser::request req = conn->get_request();           // 获取请求对象
    std::cout << "request method: " << req.get_method() << std::endl;       // 获取请求方法
    std::cout << "request uri: " << req.get_uri() << std::endl;             // 获取请求uri接口

    // 构建响应
    std::string body = "<html><body><h1>Hello World!</h1></body></html>"; // 构建按响应正文
    conn->set_body(body);                                                 // 设置响应正文
    conn->append_header("Content-Type", "text/html");                     // 添加响应报头字段
    conn->set_status(websocketpp::http::status_code::ok);                 // 设置响应状态码

    wsserver_t::timer_ptr tptr = svr->set_timer(5000, std::bind(print, "我正在测试websocketpp的计时器"));// 设置定时任务，5000ms后调用print函数，参数是...
    tptr->cancel();// 取消该定时任务，导致定时任务立即被执行
}
void wsopen_callback(wsserver_t *svr, websocketpp::connection_hdl hdl)
{
    std::cout << "websocket握手成功" << std::endl;
}
void wsclose_callback(wsserver_t *svr, websocketpp::connection_hdl hdl)
{
    std::cout << "websocket连接断开" << std::endl;
}
void wsmessage_callback(wsserver_t *svr, websocketpp::connection_hdl hdl, wsserver_t::message_ptr msg)
{
    std::cout << "websocket收到消息：" << msg->get_payload() << std::endl;
    std::string resp = "client say: " + msg->get_payload();

    wsserver_t::connection_ptr conn = svr->get_con_from_hdl(hdl);
    conn->send(resp/*, websocketpp::frame::opcode::text*/);
}
// void http_callback(websocketpp::connection_hdl hdl)
// {
//     std::cout << "收到http请求" << std::endl;
// }
// void wsopen_callback(websocketpp::connection_hdl hdl)
// {
//     std::cout << "连接成功" << std::endl;
// }
// void wsclose_callback(websocketpp::connection_hdl hdl)
// {
//     std::cout << "关闭连接成功" << std::endl;
// }
// void wsmessage_callback(websocketpp::connection_hdl hdl, wsserver_t::message_ptr msg)
// {
//     std::cout << "收到消息" << std::endl;
// }

int main()
{
    // 1. 实例化server对象
    wsserver_t wssvr;
    // 2. 设置日志等级
    wssvr.set_access_channels(websocketpp::log::alevel::none); // 不打印日志
    // 3. 初始化asio调度器
    wssvr.init_asio();
    wssvr.set_reuse_addr(true); // 设置启动地址重用
    // 4. 设置回调函数
    // wssvr.set_http_handler(http_callback);         // http请求回调
    // wssvr.set_open_handler(wsopen_callback);       // websocket握⼿成功回调
    // wssvr.set_close_handler(wsclose_callback);     // websocket连接关闭回调
    // wssvr.set_message_handler(wsmessage_callback); // websocket消息处理回调
    wssvr.set_http_handler(std::bind(http_callback, &wssvr, std::placeholders::_1));                                // http请求回调
    wssvr.set_open_handler(std::bind(wsopen_callback, &wssvr, std::placeholders::_1));                              // websocket握⼿成功回调
    wssvr.set_close_handler(std::bind(wsclose_callback, &wssvr, std::placeholders::_1));                            // websocket连接关闭回调
    wssvr.set_message_handler(std::bind(wsmessage_callback, &wssvr, std::placeholders::_1, std::placeholders::_2)); // websocket消息处理回调
    // 5. 设置监听端口
    wssvr.listen(8080);
    // 6. 开始获取新连接
    wssvr.start_accept();
    // 7. 启动服务器
    wssvr.run();

    return 0;
}